{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ch08/deep_convnet.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys, os\n",
    "sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定\n",
    "import pickle\n",
    "import numpy as np\n",
    "from collections import OrderedDict\n",
    "from common.layers import *\n",
    "\n",
    "\n",
    "class DeepConvNet:\n",
    "    \"\"\"認識率99%以上の高精度なConvNet\n",
    "\n",
    "    ネットワーク構成は下記の通り\n",
    "        conv - relu - conv- relu - pool -\n",
    "        conv - relu - conv- relu - pool -\n",
    "        conv - relu - conv- relu - pool -\n",
    "        affine - relu - dropout - affine - dropout - softmax\n",
    "    \"\"\"\n",
    "    def __init__(self, input_dim=(1, 28, 28),\n",
    "                 conv_param_1 = {'filter_num':16, 'filter_size':3, 'pad':1, 'stride':1},\n",
    "                 conv_param_2 = {'filter_num':16, 'filter_size':3, 'pad':1, 'stride':1},\n",
    "                 conv_param_3 = {'filter_num':32, 'filter_size':3, 'pad':1, 'stride':1},\n",
    "                 conv_param_4 = {'filter_num':32, 'filter_size':3, 'pad':2, 'stride':1},\n",
    "                 conv_param_5 = {'filter_num':64, 'filter_size':3, 'pad':1, 'stride':1},\n",
    "                 conv_param_6 = {'filter_num':64, 'filter_size':3, 'pad':1, 'stride':1},\n",
    "                 hidden_size=50, output_size=10):\n",
    "        # 重みの初期化===========\n",
    "        # 各層のニューロンひとつあたりが、前層のニューロンといくつのつながりがあるか（TODO:自動で計算する）\n",
    "        pre_node_nums = np.array([1*3*3, 16*3*3, 16*3*3, 32*3*3, 32*3*3, 64*3*3, 64*4*4, hidden_size])\n",
    "        weight_init_scales = np.sqrt(2.0 / pre_node_nums)  # ReLUを使う場合に推奨される初期値\n",
    "        \n",
    "        self.params = {}\n",
    "        pre_channel_num = input_dim[0]\n",
    "        for idx, conv_param in enumerate([conv_param_1, conv_param_2, conv_param_3, conv_param_4, conv_param_5, conv_param_6]):\n",
    "            self.params['W' + str(idx+1)] = weight_init_scales[idx] * np.random.randn(conv_param['filter_num'], pre_channel_num, conv_param['filter_size'], conv_param['filter_size'])\n",
    "            self.params['b' + str(idx+1)] = np.zeros(conv_param['filter_num'])\n",
    "            pre_channel_num = conv_param['filter_num']\n",
    "        self.params['W7'] = weight_init_scales[6] * np.random.randn(64*4*4, hidden_size)\n",
    "        self.params['b7'] = np.zeros(hidden_size)\n",
    "        self.params['W8'] = weight_init_scales[7] * np.random.randn(hidden_size, output_size)\n",
    "        self.params['b8'] = np.zeros(output_size)\n",
    "\n",
    "        # レイヤの生成===========\n",
    "        self.layers = []\n",
    "        self.layers.append(Convolution(self.params['W1'], self.params['b1'], \n",
    "                           conv_param_1['stride'], conv_param_1['pad']))\n",
    "        self.layers.append(Relu())\n",
    "        self.layers.append(Convolution(self.params['W2'], self.params['b2'], \n",
    "                           conv_param_2['stride'], conv_param_2['pad']))\n",
    "        self.layers.append(Relu())\n",
    "        self.layers.append(Pooling(pool_h=2, pool_w=2, stride=2))\n",
    "        self.layers.append(Convolution(self.params['W3'], self.params['b3'], \n",
    "                           conv_param_3['stride'], conv_param_3['pad']))\n",
    "        self.layers.append(Relu())\n",
    "        self.layers.append(Convolution(self.params['W4'], self.params['b4'],\n",
    "                           conv_param_4['stride'], conv_param_4['pad']))\n",
    "        self.layers.append(Relu())\n",
    "        self.layers.append(Pooling(pool_h=2, pool_w=2, stride=2))\n",
    "        self.layers.append(Convolution(self.params['W5'], self.params['b5'],\n",
    "                           conv_param_5['stride'], conv_param_5['pad']))\n",
    "        self.layers.append(Relu())\n",
    "        self.layers.append(Convolution(self.params['W6'], self.params['b6'],\n",
    "                           conv_param_6['stride'], conv_param_6['pad']))\n",
    "        self.layers.append(Relu())\n",
    "        self.layers.append(Pooling(pool_h=2, pool_w=2, stride=2))\n",
    "        self.layers.append(Affine(self.params['W7'], self.params['b7']))\n",
    "        self.layers.append(Relu())\n",
    "        self.layers.append(Dropout(0.5))\n",
    "        self.layers.append(Affine(self.params['W8'], self.params['b8']))\n",
    "        self.layers.append(Dropout(0.5))\n",
    "        \n",
    "        self.last_layer = SoftmaxWithLoss()\n",
    "\n",
    "    def predict(self, x, train_flg=False):\n",
    "        for layer in self.layers:\n",
    "            if isinstance(layer, Dropout):\n",
    "                x = layer.forward(x, train_flg)\n",
    "            else:\n",
    "                x = layer.forward(x)\n",
    "        return x\n",
    "\n",
    "    def loss(self, x, t):\n",
    "        y = self.predict(x, train_flg=True)\n",
    "        return self.last_layer.forward(y, t)\n",
    "\n",
    "    def accuracy(self, x, t, batch_size=100):\n",
    "        if t.ndim != 1 : t = np.argmax(t, axis=1)\n",
    "\n",
    "        acc = 0.0\n",
    "\n",
    "        for i in range(int(x.shape[0] / batch_size)):\n",
    "            tx = x[i*batch_size:(i+1)*batch_size]\n",
    "            tt = t[i*batch_size:(i+1)*batch_size]\n",
    "            y = self.predict(tx, train_flg=False)\n",
    "            y = np.argmax(y, axis=1)\n",
    "            acc += np.sum(y == tt)\n",
    "\n",
    "        return acc / x.shape[0]\n",
    "\n",
    "    def gradient(self, x, t):\n",
    "        # forward\n",
    "        self.loss(x, t)\n",
    "\n",
    "        # backward\n",
    "        dout = 1\n",
    "        dout = self.last_layer.backward(dout)\n",
    "\n",
    "        tmp_layers = self.layers.copy()\n",
    "        tmp_layers.reverse()\n",
    "        for layer in tmp_layers:\n",
    "            dout = layer.backward(dout)\n",
    "\n",
    "        # 設定\n",
    "        grads = {}\n",
    "        for i, layer_idx in enumerate((0, 2, 5, 7, 10, 12, 15, 18)):\n",
    "            grads['W' + str(i+1)] = self.layers[layer_idx].dW\n",
    "            grads['b' + str(i+1)] = self.layers[layer_idx].db\n",
    "\n",
    "        return grads\n",
    "\n",
    "    def save_params(self, file_name=\"params.pkl\"):\n",
    "        params = {}\n",
    "        for key, val in self.params.items():\n",
    "            params[key] = val\n",
    "        with open(file_name, 'wb') as f:\n",
    "            pickle.dump(params, f)\n",
    "\n",
    "    def load_params(self, file_name=\"params.pkl\"):\n",
    "        with open(file_name, 'rb') as f:\n",
    "            params = pickle.load(f)\n",
    "        for key, val in params.items():\n",
    "            self.params[key] = val\n",
    "\n",
    "        for i, layer_idx in enumerate((0, 2, 5, 7, 10, 12, 15, 18)):\n",
    "            self.layers[layer_idx].W = self.params['W' + str(i+1)]\n",
    "            self.layers[layer_idx].b = self.params['b' + str(i+1)]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ch08/awesome_net.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create your awesome net!!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ch08/train_deepnet.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train loss:2.2601293080561025\n",
      "=== epoch:1, train acc:0.0, test acc:0.0 ===\n",
      "train loss:2.256545712046532\n",
      "train loss:2.284060130168717\n",
      "train loss:2.2828344026167513\n",
      "train loss:2.260370150621531\n",
      "train loss:2.2666123190173395\n",
      "train loss:2.2553712009202336\n",
      "train loss:2.268849770615311\n",
      "train loss:2.222922504714054\n",
      "train loss:2.193975318833982\n",
      "train loss:2.19171957684596\n",
      "train loss:2.2206838671785225\n",
      "train loss:2.2073249055185142\n",
      "train loss:2.204823883607731\n",
      "train loss:2.1456796571019257\n",
      "train loss:2.2336465793567437\n",
      "train loss:2.156033860427046\n",
      "train loss:2.105963774641744\n",
      "train loss:2.0212952038421865\n",
      "train loss:2.06256746038964\n",
      "train loss:2.108966733251184\n",
      "train loss:2.0558179677934176\n",
      "train loss:2.082261334365555\n",
      "train loss:1.908551579551048\n",
      "train loss:2.0245485363791773\n",
      "train loss:2.0732120617972276\n",
      "train loss:2.0164425360959375\n",
      "train loss:2.040589462285194\n",
      "train loss:2.035573957457666\n",
      "train loss:2.00988576249831\n",
      "train loss:1.9694219549347591\n",
      "train loss:1.7303101074682965\n",
      "train loss:1.8778477336479853\n",
      "train loss:1.9982820675547182\n",
      "train loss:1.760015570734016\n",
      "train loss:1.8062319883946396\n",
      "train loss:1.884135453856337\n",
      "train loss:1.6295396362580836\n",
      "train loss:1.8696261857098162\n",
      "train loss:1.7279795515764098\n",
      "train loss:1.7729782413076398\n",
      "train loss:1.7897871947408277\n",
      "train loss:1.604064920948552\n",
      "train loss:1.8141379938691944\n",
      "train loss:1.718522159269352\n",
      "train loss:1.6846777995008344\n",
      "train loss:1.7854024994470965\n",
      "train loss:1.7056660959360355\n",
      "train loss:1.671253752818701\n",
      "train loss:1.6563085736310512\n",
      "train loss:1.7244292052433252\n",
      "train loss:1.7855844770737626\n",
      "train loss:1.6811750193244746\n",
      "train loss:1.6736575408630978\n",
      "train loss:1.5747665736977234\n",
      "train loss:1.8339856301098223\n",
      "train loss:1.7386683021246803\n",
      "train loss:1.4367708681817857\n",
      "train loss:1.593868849305551\n",
      "train loss:1.691404320090949\n",
      "train loss:1.743653971057333\n",
      "train loss:1.5277519812327387\n",
      "train loss:1.727332297171094\n",
      "train loss:1.7959081749558399\n",
      "train loss:1.588610785904911\n",
      "train loss:1.5541948944524677\n",
      "train loss:1.5758708589976118\n",
      "train loss:1.611308486408034\n",
      "train loss:1.664395992358469\n",
      "train loss:1.4096373256622377\n",
      "train loss:1.6346992841863512\n",
      "train loss:1.5979109563196707\n",
      "train loss:1.6796824803153059\n",
      "train loss:1.5598587331048424\n",
      "train loss:1.7463163924751768\n",
      "train loss:1.4356944554505349\n",
      "train loss:1.5572949830679783\n",
      "train loss:1.5657757475973677\n",
      "train loss:1.662924580901175\n",
      "train loss:1.4390567317805858\n",
      "train loss:1.4970115513799525\n",
      "train loss:1.624055458110132\n",
      "train loss:1.5572629347362366\n",
      "train loss:1.5420252446875997\n",
      "train loss:1.5941103913058328\n",
      "train loss:1.7045176818166423\n",
      "train loss:1.5262573025659618\n",
      "train loss:1.4629580013236454\n",
      "train loss:1.5048406047684404\n",
      "train loss:1.300967830134459\n",
      "train loss:1.4424511561428537\n",
      "train loss:1.4901576020145755\n",
      "train loss:1.6688876678515874\n",
      "train loss:1.477739370806794\n",
      "train loss:1.4613240345525225\n",
      "train loss:1.5206354824160966\n",
      "train loss:1.6929297681095088\n",
      "train loss:1.5643375929887646\n",
      "train loss:1.3679386752308325\n",
      "train loss:1.4177790685362779\n",
      "train loss:1.449430108401551\n",
      "train loss:1.4959332219003065\n",
      "train loss:1.5085807655407069\n",
      "train loss:1.3442756180364368\n",
      "train loss:1.3969838242176231\n",
      "train loss:1.4437089831491912\n",
      "train loss:1.2548592063026298\n",
      "train loss:1.4588212440198862\n",
      "train loss:1.309900338250754\n",
      "train loss:1.4550490423885254\n",
      "train loss:1.4638944067048567\n",
      "train loss:1.467825990141045\n",
      "train loss:1.3162114196386363\n",
      "train loss:1.4928602953576589\n",
      "train loss:1.2824057135508817\n",
      "train loss:1.4276592630121658\n",
      "train loss:1.481985715211585\n",
      "train loss:1.287289713130271\n",
      "train loss:1.1848523293719933\n",
      "train loss:1.4816479728896357\n",
      "train loss:1.414260730906478\n",
      "train loss:1.4758921099122626\n",
      "train loss:1.1583415111450568\n",
      "train loss:1.3199439317503714\n",
      "train loss:1.467816202178292\n",
      "train loss:1.38737232484027\n",
      "train loss:1.2583751234754026\n",
      "train loss:1.5702187587589556\n",
      "train loss:1.1607263311259948\n",
      "train loss:1.1866867076114689\n",
      "train loss:1.3562599377834172\n",
      "train loss:1.2716870667854863\n",
      "train loss:1.5476304995076255\n",
      "train loss:1.302667292113394\n",
      "train loss:1.1857046776478095\n",
      "train loss:1.2836281828459881\n",
      "train loss:1.3655759883585867\n",
      "train loss:1.4479828235810774\n",
      "train loss:1.18181147688468\n",
      "train loss:1.3429696005817238\n",
      "train loss:1.295810238125911\n",
      "train loss:1.3841984415483544\n",
      "train loss:1.2973356588772322\n",
      "train loss:1.4537481615554566\n",
      "train loss:1.322217883934983\n",
      "train loss:1.3302735258627727\n",
      "train loss:1.498710450955122\n",
      "train loss:1.323224563845438\n",
      "train loss:1.2887114383296103\n",
      "train loss:1.211756131768424\n",
      "train loss:1.358063609240253\n",
      "train loss:1.424199817653623\n",
      "train loss:1.052748361688476\n",
      "train loss:1.2788728478223472\n",
      "train loss:1.25548540769216\n",
      "train loss:1.5308391473696574\n",
      "train loss:1.261283043863443\n",
      "train loss:1.3400084535305279\n",
      "train loss:1.2689217676418172\n",
      "train loss:1.3735424750388818\n",
      "train loss:1.2442523305055215\n",
      "train loss:1.2957412434833568\n",
      "train loss:1.4282126562736455\n",
      "train loss:1.2857953486256684\n",
      "train loss:1.3386668475516124\n",
      "train loss:1.3219217051261898\n",
      "train loss:1.5829544897648191\n",
      "train loss:1.1987503313137873\n",
      "train loss:1.3625791370002427\n",
      "train loss:1.4353729261316388\n",
      "train loss:1.4009637385521034\n",
      "train loss:1.0679994816496505\n",
      "train loss:1.2884028011874082\n",
      "train loss:1.291981205388173\n",
      "train loss:1.307839213673553\n",
      "train loss:1.4648598139631523\n",
      "train loss:1.3772926171969604\n",
      "train loss:1.5695036076471314\n",
      "train loss:1.2393220030355148\n",
      "train loss:1.1783372494762485\n",
      "train loss:1.486029699288145\n",
      "train loss:1.3001173462328415\n",
      "train loss:1.186817662525383\n",
      "train loss:1.2994132280102266\n",
      "train loss:1.3554268522644426\n",
      "train loss:0.9646881596297868\n",
      "train loss:1.3992082600424651\n",
      "train loss:1.2554152920135437\n",
      "train loss:1.2900012843990059\n",
      "train loss:1.3419732848701076\n",
      "train loss:1.1499872811954837\n",
      "train loss:1.0754953911153864\n",
      "train loss:1.4085718618832828\n",
      "train loss:1.3902132941280996\n",
      "train loss:1.1307429452051923\n",
      "train loss:1.1212143260343188\n",
      "train loss:1.0971705484402134\n",
      "train loss:1.1795891091399937\n",
      "train loss:1.2458412815236446\n",
      "train loss:1.3127186387451792\n",
      "train loss:1.3334433159120593\n",
      "train loss:1.3077000604855855\n",
      "train loss:1.2574340232331473\n",
      "train loss:1.1614163903921346\n",
      "train loss:1.3757410869606352\n",
      "train loss:1.1213448499420806\n",
      "train loss:1.2018004620148142\n",
      "train loss:1.316268650114248\n",
      "train loss:1.1634606500935332\n",
      "train loss:1.268307413676781\n",
      "train loss:1.4479363156864644\n",
      "train loss:1.2865663813444232\n",
      "train loss:1.4121269808107264\n",
      "train loss:1.134390621464617\n",
      "train loss:1.4505241890649838\n",
      "train loss:1.4176069089208942\n",
      "train loss:1.2955730837534094\n",
      "train loss:1.2114074801186374\n",
      "train loss:1.234005884269477\n",
      "train loss:1.434543830826123\n",
      "train loss:1.3100821381948036\n",
      "train loss:1.3159851741642326\n",
      "train loss:1.2622562307379672\n",
      "train loss:1.0475980137467686\n",
      "train loss:1.2520434273213845\n",
      "train loss:0.9295855182440209\n",
      "train loss:1.1172156937320878\n",
      "train loss:1.2048365659334497\n",
      "train loss:1.104227280400387\n",
      "train loss:1.144891994048708\n",
      "train loss:1.122610780544766\n",
      "train loss:1.1893538586655965\n",
      "train loss:1.1601837934606218\n",
      "train loss:1.2791242478650047\n",
      "train loss:1.2178391622675355\n",
      "train loss:1.3053974391877008\n",
      "train loss:1.1220675245971479\n",
      "train loss:1.2103531229398745\n",
      "train loss:1.412601733660872\n",
      "train loss:1.21147281792278\n",
      "train loss:1.3311521517467435\n",
      "train loss:1.1435320179363695\n",
      "train loss:1.2295695050285003\n",
      "train loss:1.3281474510970306\n",
      "train loss:1.075945134589148\n",
      "train loss:1.1551869818034763\n",
      "train loss:1.1382141302120825\n",
      "train loss:1.181115829762949\n",
      "train loss:1.2500827397161538\n",
      "train loss:1.2344228411619023\n",
      "train loss:1.2699862608482149\n",
      "train loss:1.1091951913032982\n",
      "train loss:1.1681443538721172\n",
      "train loss:1.2530612462996127\n",
      "train loss:1.1985008164302342\n",
      "train loss:1.0568703807540616\n",
      "train loss:1.2007300889857924\n",
      "train loss:1.0729216685014342\n",
      "train loss:1.1827368578725643\n",
      "train loss:1.0269226748955904\n",
      "train loss:1.4373883730590742\n",
      "train loss:1.1035875686910352\n",
      "train loss:0.9967715460392654\n",
      "train loss:1.0908047242169516\n",
      "train loss:1.1122028219804116\n",
      "train loss:1.0834267599108904\n",
      "train loss:1.1497618170591812\n",
      "train loss:1.1815806138308254\n",
      "train loss:1.3181555333129564\n",
      "train loss:1.2847769510569287\n",
      "train loss:1.1343695788487482\n",
      "train loss:1.2352917220454647\n",
      "train loss:1.0899546115606389\n",
      "train loss:1.1951984126485171\n",
      "train loss:1.2271231118652428\n",
      "train loss:1.0777324474464915\n",
      "train loss:1.1167210062153934\n",
      "train loss:1.2040335916965026\n",
      "train loss:1.4286588799965003\n",
      "train loss:1.0974192112526044\n",
      "train loss:1.0294889601232855\n",
      "train loss:1.1384435780016893\n",
      "train loss:1.1646593661832565\n",
      "train loss:1.2237096464054589\n",
      "train loss:1.1994585144460592\n",
      "train loss:1.152022204969826\n",
      "train loss:0.9556939266632708\n",
      "train loss:1.284777163320466\n",
      "train loss:1.0236228104671476\n",
      "train loss:1.0995571379088316\n",
      "train loss:1.068160257487191\n",
      "train loss:1.1973741154252835\n",
      "train loss:1.1272919385340203\n",
      "train loss:1.201798868319181\n",
      "train loss:1.3791808625229478\n",
      "train loss:1.0260882640060578\n",
      "train loss:1.069237114784766\n",
      "train loss:1.1359629127499484\n",
      "train loss:1.2717530888230515\n",
      "train loss:1.0182036851973466\n",
      "train loss:1.2269299256600914\n",
      "train loss:1.262989545106054\n",
      "train loss:1.1883152324014297\n",
      "train loss:1.0923488302345072\n",
      "train loss:0.9429996248039245\n",
      "train loss:1.0611625695318876\n",
      "train loss:0.9821927903711472\n",
      "train loss:1.234915697167248\n",
      "train loss:1.31407144988141\n",
      "train loss:1.2097696926187185\n",
      "train loss:1.2277646411176386\n",
      "train loss:1.156355846736909\n",
      "train loss:1.20701802806152\n",
      "train loss:1.1296616057260644\n",
      "train loss:1.2258798545233602\n",
      "train loss:1.1117907499424917\n",
      "train loss:0.9149996804499742\n",
      "train loss:1.2080381037455286\n",
      "train loss:0.953679674308547\n",
      "train loss:0.9814455923908456\n",
      "train loss:1.2429658895928029\n",
      "train loss:1.0643949025967254\n",
      "train loss:1.2016660066876377\n",
      "train loss:1.1949315306747323\n",
      "train loss:1.219457786765221\n",
      "train loss:1.0212701497899255\n",
      "train loss:1.140843866774741\n",
      "train loss:1.2572465326516216\n",
      "train loss:1.1261048722234603\n",
      "train loss:1.0176528331843802\n",
      "train loss:1.19064946473899\n",
      "train loss:1.383512765943497\n",
      "train loss:1.0180472594972798\n",
      "train loss:1.0495537679534999\n",
      "train loss:1.10964937704192\n",
      "train loss:1.3178376241884253\n",
      "train loss:1.2266855428457661\n",
      "train loss:1.1469642405599312\n",
      "train loss:1.095806777466841\n",
      "train loss:1.2330500616611666\n",
      "train loss:1.2285386629923989\n",
      "train loss:1.2839426848701405\n",
      "train loss:0.9711930299415995\n",
      "train loss:1.1604266692717418\n",
      "train loss:1.0906528816227201\n",
      "train loss:0.9742104530261321\n",
      "train loss:1.2354379131950515\n",
      "train loss:1.1248160164995362\n",
      "train loss:1.194492536950252\n",
      "train loss:1.1052270272198648\n",
      "train loss:1.2565248515143836\n",
      "train loss:1.0843329428093664\n",
      "train loss:1.2287706034766548\n",
      "train loss:1.102211972839975\n",
      "train loss:1.2259688702037288\n",
      "train loss:1.1712871558908378\n",
      "train loss:1.228345971700178\n",
      "train loss:1.1637804464024513\n",
      "train loss:1.2801586133461182\n",
      "train loss:1.3208820219428545\n",
      "train loss:1.1696022190144404\n",
      "train loss:1.2572439734435275\n",
      "train loss:1.0254579045473837\n",
      "train loss:0.9968309244952169\n",
      "train loss:1.179755279063094\n",
      "train loss:0.9999407633009835\n",
      "train loss:1.083527279594643\n",
      "train loss:1.1000718895364328\n",
      "train loss:1.076036106020487\n",
      "train loss:1.1094454587474836\n",
      "train loss:0.9380149968943908\n",
      "train loss:1.1255809630014852\n",
      "train loss:1.0353147667413694\n",
      "train loss:1.1646811741148224\n",
      "train loss:1.1148033536616875\n",
      "train loss:1.29930002402188\n",
      "train loss:1.3336412838306095\n",
      "train loss:1.1434608479911994\n",
      "train loss:1.2097645784280062\n",
      "train loss:1.2054824346452016\n",
      "train loss:1.38892958407764\n",
      "train loss:1.368880631382933\n",
      "train loss:1.094362395470962\n",
      "train loss:1.2184124642026013\n",
      "train loss:1.184983455198198\n",
      "train loss:1.1917720737004949\n",
      "train loss:1.2083786275829704\n",
      "train loss:1.1849750157230663\n",
      "train loss:1.165468590450882\n",
      "train loss:1.2921319764130847\n",
      "train loss:1.1427637066717495\n",
      "train loss:1.2004619577200817\n",
      "train loss:1.0657533051236723\n",
      "train loss:1.363056274174425\n",
      "train loss:1.0664969713124797\n",
      "train loss:1.071501647933086\n",
      "train loss:1.1717284058417763\n",
      "train loss:1.1668278014329252\n",
      "train loss:1.004307668854485\n",
      "train loss:1.4052524336111099\n",
      "train loss:0.949854037099919\n",
      "train loss:0.9920059812786411\n",
      "train loss:1.0080309533201197\n",
      "train loss:1.0188963371878188\n",
      "train loss:0.9490920812187662\n",
      "train loss:1.048717408490424\n",
      "train loss:0.9183690913959505\n",
      "train loss:0.9974856853650433\n",
      "train loss:1.1162006621182499\n",
      "train loss:1.2934451197515455\n",
      "train loss:1.1085230119428116\n",
      "train loss:0.9210429126424651\n",
      "train loss:0.9999412895149118\n",
      "train loss:1.0532755671804805\n",
      "train loss:0.9932572162300821\n",
      "train loss:1.028365310655558\n",
      "train loss:1.1936300127932977\n",
      "train loss:1.1479012971878633\n",
      "train loss:1.0558711160235512\n",
      "train loss:1.2578531332916503\n",
      "train loss:1.1043954346053246\n",
      "train loss:1.0248835933698344\n",
      "train loss:1.195589569650791\n",
      "train loss:1.1740385413910372\n",
      "train loss:1.0086251371314816\n",
      "train loss:1.069194952592319\n",
      "train loss:1.0698714283453914\n",
      "train loss:1.0017823976965947\n",
      "train loss:1.2703659808258265\n",
      "train loss:1.1988775184401104\n",
      "train loss:0.9606174081473629\n",
      "train loss:1.0132041555933864\n",
      "train loss:1.0032524479142872\n",
      "train loss:0.9356334166112525\n",
      "train loss:1.194672233553884\n",
      "train loss:1.1761196000432954\n",
      "train loss:0.9943081769325701\n",
      "train loss:0.8471407719951562\n",
      "train loss:1.1812872034144932\n",
      "train loss:1.1650846796319962\n",
      "train loss:1.0273549765894372\n",
      "train loss:0.931105207831319\n",
      "train loss:1.1008391987735393\n",
      "train loss:0.9442224057400616\n",
      "train loss:1.144600564716206\n",
      "train loss:1.03050766822187\n",
      "train loss:1.2329248106931554\n",
      "train loss:0.9254274522232925\n",
      "train loss:1.1116096248445837\n",
      "train loss:1.1465411071792706\n",
      "train loss:1.1435472884436408\n",
      "train loss:1.0903252805787023\n",
      "train loss:0.8142451514518061\n",
      "train loss:1.2560220390034\n",
      "train loss:1.1077870725718282\n",
      "train loss:1.128841919899868\n",
      "train loss:1.0468514949698489\n",
      "train loss:1.0576103577997729\n",
      "train loss:1.0444358125820468\n",
      "train loss:0.9490132696818921\n",
      "train loss:1.0138137500769877\n",
      "train loss:1.0733918806781926\n",
      "train loss:1.3440598806372268\n",
      "train loss:1.1061067354707574\n",
      "train loss:0.9608506602348642\n",
      "train loss:0.996732897377956\n",
      "train loss:0.992352084932018\n",
      "train loss:0.8192633529204801\n",
      "train loss:1.0769997597457246\n",
      "train loss:1.0805671966937687\n",
      "train loss:1.0722575416850626\n",
      "train loss:0.9956724557174198\n",
      "train loss:1.0331145221760574\n",
      "train loss:0.9879279265004566\n",
      "train loss:1.0780042948160422\n",
      "train loss:1.029693164718788\n",
      "train loss:0.8587550381628033\n",
      "train loss:1.038864547407906\n",
      "train loss:1.0596704560218375\n",
      "train loss:1.1515218382322976\n",
      "train loss:1.1394639582163806\n",
      "train loss:0.9255903065294558\n",
      "train loss:0.91000905253579\n",
      "train loss:1.2735264032877074\n",
      "train loss:0.9032851436345186\n",
      "train loss:1.0177038874607292\n",
      "train loss:0.9665653297111367\n",
      "train loss:0.9187809877572937\n",
      "train loss:1.074611766006513\n",
      "train loss:1.1380752409612407\n",
      "train loss:0.9468717405637763\n",
      "train loss:1.1394226387671926\n",
      "train loss:1.0907497491604299\n",
      "train loss:1.0759392437938922\n",
      "train loss:1.2158339344142908\n",
      "train loss:0.9805725189311777\n",
      "train loss:1.1507715376439205\n",
      "train loss:0.9434922552667122\n",
      "train loss:1.095519343744477\n",
      "train loss:1.0994414614263506\n",
      "train loss:1.2548651569148241\n",
      "train loss:0.9528523301774338\n",
      "train loss:1.021529054592062\n",
      "train loss:1.2226620320482713\n",
      "train loss:1.1464016228287652\n",
      "train loss:1.0050518552674095\n",
      "train loss:1.0861170846137973\n",
      "train loss:1.068219383499011\n",
      "train loss:1.0696939128192826\n",
      "train loss:1.0056145973114947\n",
      "train loss:0.9025938225046479\n",
      "train loss:0.9697210736974866\n",
      "train loss:1.0885767686299268\n",
      "train loss:0.9961763378330288\n",
      "train loss:1.1079462691861364\n",
      "train loss:0.8961518128448829\n",
      "train loss:1.0564354854384437\n",
      "train loss:0.9119238245853586\n",
      "train loss:1.0918698183826434\n",
      "train loss:0.9993310153233236\n",
      "train loss:0.8617959640563266\n",
      "train loss:1.1218775233759006\n",
      "train loss:1.1786180272163407\n",
      "train loss:1.060688355155622\n",
      "train loss:1.1376005040590673\n",
      "train loss:0.8700961985376563\n",
      "train loss:1.1230175881352071\n",
      "train loss:1.1477616523180194\n",
      "train loss:1.1903379719516123\n",
      "train loss:1.0531357240997625\n",
      "train loss:1.0580150618232056\n",
      "train loss:1.1593834207784555\n",
      "train loss:1.1499443211094136\n",
      "train loss:1.097781076306909\n",
      "train loss:1.0631206578318388\n",
      "train loss:0.8478188663655566\n",
      "train loss:1.0349401741723465\n",
      "train loss:0.96940266558463\n",
      "train loss:1.0088085535632814\n",
      "train loss:0.9652749688695438\n",
      "train loss:0.9797400242422133\n",
      "train loss:0.9690746601402364\n",
      "train loss:1.0437012586927426\n",
      "train loss:1.1687742978881468\n",
      "train loss:1.1039674541619882\n",
      "train loss:1.04693020540291\n",
      "train loss:1.0071450815225882\n",
      "train loss:1.0802337605123857\n",
      "train loss:1.1511585658508805\n",
      "train loss:1.2431655279670561\n",
      "train loss:1.1508292439734351\n",
      "train loss:0.906233246614859\n",
      "train loss:1.149755284967908\n",
      "train loss:0.9856545521070439\n",
      "train loss:0.9663327533721686\n",
      "train loss:1.0481283215010855\n",
      "train loss:1.220802508573019\n",
      "train loss:0.9093053722699119\n",
      "train loss:0.9359988217754569\n",
      "train loss:0.9398231035987237\n",
      "train loss:1.1866600264610287\n",
      "train loss:1.0473371387298878\n",
      "train loss:1.066243712792053\n",
      "train loss:0.9114245256738792\n",
      "train loss:1.0581482655307775\n",
      "train loss:0.9572868565080325\n",
      "train loss:0.8064550127284968\n",
      "train loss:1.0976097145477604\n",
      "train loss:1.1597535334719773\n",
      "train loss:1.0563765738102242\n",
      "train loss:1.0997358515124978\n",
      "train loss:1.0402686516008794\n",
      "train loss:0.8818350180094211\n",
      "train loss:1.0490456366600829\n",
      "train loss:1.0550413426495977\n",
      "train loss:1.0924665964964302\n",
      "train loss:0.9591065083194983\n",
      "train loss:1.1492556081573098\n",
      "train loss:0.9373159581526969\n",
      "train loss:0.972168297669645\n",
      "train loss:1.000236007314943\n",
      "train loss:0.9548399415665595\n",
      "train loss:1.0384864917226528\n",
      "train loss:0.9548760006157615\n",
      "train loss:1.1811544313604037\n",
      "train loss:1.0119584988868957\n",
      "train loss:1.2244669941708257\n",
      "train loss:1.1382654776987189\n",
      "train loss:1.0809084057706784\n",
      "train loss:1.0657138254665555\n",
      "train loss:1.0866042615718623\n",
      "train loss:1.0008656249112697\n",
      "train loss:0.9406486825048952\n",
      "train loss:1.24641213544415\n",
      "train loss:0.9922270541439637\n",
      "train loss:1.0451549623784402\n",
      "train loss:1.1364449446530367\n",
      "train loss:0.9576321362010053\n",
      "train loss:0.9506883861415367\n",
      "train loss:0.981877743770104\n",
      "=============== Final Test Accuracy ===============\n",
      "test acc:0.9797\n",
      "Saved Network Parameters!\n"
     ]
    }
   ],
   "source": [
    "import sys, os\n",
    "sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from dataset.mnist import load_mnist\n",
    "from common.trainer import Trainer\n",
    "\n",
    "(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)\n",
    "\n",
    "network = DeepConvNet()  \n",
    "trainer = Trainer(network, x_train, t_train, x_test, t_test,\n",
    "                  epochs=20, mini_batch_size=100,\n",
    "                  optimizer='Adam', optimizer_param={'lr':0.001},\n",
    "                  evaluate_sample_num_per_epoch=1000)\n",
    "trainer.train()\n",
    "\n",
    "# パラメータの保存\n",
    "network.save_params(\"../ch08/deep_convnet_params.pkl\")\n",
    "print(\"Saved Network Parameters!\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ch08/misclassified_mnist.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "calculating test accuracy ... \n",
      "test accuracy:0.9797\n",
      "======= misclassified result =======\n",
      "{view index: (label, inference), ...}\n",
      "{1: (9, 8), 2: (9, 8), 3: (9, 8), 4: (6, 0), 5: (8, 5), 6: (9, 8), 7: (2, 7), 8: (6, 0), 9: (4, 1), 10: (4, 9), 11: (3, 2), 12: (8, 2), 13: (8, 2), 14: (1, 8), 15: (3, 9), 16: (7, 2), 17: (1, 7), 18: (5, 8), 19: (4, 9), 20: (4, 9)}\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAbYAAAExCAYAAAAQvIcQAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAAsTAAALEwEAmpwYAAAyaUlEQVR4nO3debxN9f7H8depVEKRI8mNE0UqjRokJd2SCklSSpKii2imUqJ5ciUaVCSVpAFNmqXcKPolStQVEspxFTKkOr8/PD7ru/bZ+xxn2ON3v5//nGXttff+Wmefvdbn+/18P9+cgoICREREfLFDqhsgIiIST7qwiYiIV3RhExERr+jCJiIiXtGFTUREvLJTaQ7Ozc0tyMvLS1BT0teSJUvIz8/PScZ7Zes5BpgzZ05+QUFBjUS/j85x4s8xZO951vdFchT3WS7VhS0vL4/Zs2fHp1UZpEmTJkl7r2w9xwA5OTlLk/E+OsfJka3nWd8XyVHcZ1ldkSIi4hVd2ERExCu6sImIiFd0YRMREa/owiYiIl4pVVakiEg6mTdvHgAtW7YEID8/H4DPP/88OCaZWYqSHhSxiYiIVxSxiUhG6d69e7A9btw4AP78808AGjRoAMDee++d/IZJ2lDEJiIiXlHEliWef/75YNsqFQwbNqzI420B2qZNmwLQpk0bAHr06BEcU7169Xg3M6OtWLEi2H700UcBd94XL14cdXy3bt0ANz7UqVMnACpUqJDQdma6t99+O9guHKlNnToVgH/84x/Jb5inGjduDMD8+fMBOPnkkwH44IMPUtam7VHEJiIiXsnIiO2dd94BYODAgYDLgBo8eHBwjD22ww7Zee22//+IESMA2LRpU/CY3eXm5Gy/TuusWbMifloWGkRGgdno77//Btx5uPPOO4PHvv322+0+f8yYMRE/7fnvv/9+cMw+++wTn8Z6oFevXgD8/PPPwb6GDRsC8NZbbwHbaidK+V111VXB9tdffx3xWPPmzZPcmtLLzm99ERHxli5sIiLilYzpirRBYYALLrgAgN9++w1wXWq33XZbcMx1110HwG677ZakFqaHm266CYChQ4cCsHXr1qhj9thjDwDOPvtsAM466ywAdt555+CYtm3bxnz9//73v8G2TYbNzc0tZ6sz05NPPglAz549ox7bfffdAbj44osB2H///aOO+e677wB4/PHH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\n",
      "text/plain": [
       "<Figure size 432x288 with 20 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import sys, os\n",
    "sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from dataset.mnist import load_mnist\n",
    "\n",
    "\n",
    "(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)\n",
    "\n",
    "network = DeepConvNet()\n",
    "network.load_params(\"../ch08/deep_convnet_params.pkl\")\n",
    "\n",
    "print(\"calculating test accuracy ... \")\n",
    "#sampled = 1000\n",
    "#x_test = x_test[:sampled]\n",
    "#t_test = t_test[:sampled]\n",
    "\n",
    "classified_ids = []\n",
    "\n",
    "acc = 0.0\n",
    "batch_size = 100\n",
    "\n",
    "for i in range(int(x_test.shape[0] / batch_size)):\n",
    "    tx = x_test[i*batch_size:(i+1)*batch_size]\n",
    "    tt = t_test[i*batch_size:(i+1)*batch_size]\n",
    "    y = network.predict(tx, train_flg=False)\n",
    "    y = np.argmax(y, axis=1)\n",
    "    classified_ids.append(y)\n",
    "    acc += np.sum(y == tt)\n",
    "    \n",
    "acc = acc / x_test.shape[0]\n",
    "print(\"test accuracy:\" + str(acc))\n",
    "\n",
    "classified_ids = np.array(classified_ids)\n",
    "classified_ids = classified_ids.flatten()\n",
    " \n",
    "max_view = 20\n",
    "current_view = 1\n",
    "\n",
    "fig = plt.figure()\n",
    "fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.2, wspace=0.2)\n",
    "\n",
    "mis_pairs = {}\n",
    "for i, val in enumerate(classified_ids == t_test):\n",
    "    if not val:\n",
    "        ax = fig.add_subplot(4, 5, current_view, xticks=[], yticks=[])\n",
    "        ax.imshow(x_test[i].reshape(28, 28), cmap=plt.cm.gray_r, interpolation='nearest')\n",
    "        mis_pairs[current_view] = (t_test[i], classified_ids[i])\n",
    "            \n",
    "        current_view += 1\n",
    "        if current_view > max_view:\n",
    "            break\n",
    "\n",
    "print(\"======= misclassified result =======\")\n",
    "print(\"{view index: (label, inference), ...}\")\n",
    "print(mis_pairs)\n",
    "\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ch08/half_float_network.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "caluculate accuracy (float64) ... \n",
      "0.9797\n",
      "caluculate accuracy (float16) ... \n",
      "0.9798\n"
     ]
    }
   ],
   "source": [
    "import sys, os\n",
    "sys.path.append(os.pardir)  # 親ディレクトリのファイルをインポートするための設定\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from dataset.mnist import load_mnist\n",
    "\n",
    "\n",
    "(x_train, t_train), (x_test, t_test) = load_mnist(flatten=False)\n",
    "\n",
    "network = DeepConvNet()\n",
    "network.load_params(\"../ch08/deep_convnet_params.pkl\")\n",
    "\n",
    "sampled = 10000 # 高速化のため\n",
    "x_test = x_test[:sampled]\n",
    "t_test = t_test[:sampled]\n",
    "\n",
    "print(\"caluculate accuracy (float64) ... \")\n",
    "print(network.accuracy(x_test, t_test))\n",
    "\n",
    "# float16に型変換\n",
    "x_test = x_test.astype(np.float16)\n",
    "for param in network.params.values():\n",
    "    param[...] = param.astype(np.float16)\n",
    "\n",
    "print(\"caluculate accuracy (float16) ... \")\n",
    "print(network.accuracy(x_test, t_test))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "dezero:Python",
   "language": "python",
   "name": "conda-env-dezero-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
